package com.haochu.novel.ui;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;

import com.haochu.novel.db.DBHelper;
import com.haochu.novel.util.Constants;
import com.haochu.novel.vo.Category;

/**
 * @author Administrator
 *
 */
@SuppressLint("SdCardPath")
public class BookFactory{
	
	// 文件内存映射方案，读写性能极高
	private MappedByteBuffer mappedByteBuffer;
	// 文件流总长度
	private long totalLength;
	// 正文画笔
	private Paint mTextPaint;
	// 标题画笔
	private Paint mTitlePaint;
	// 章节目录画笔
	private Paint mSecTitlePaint;
	// 分页百分比画笔
	private Paint mPagePercentPaint;
	// 分页百分比画笔
	private Paint mPagePercentPaint2;
	// 分页页码画笔
	private Paint mPaginationPaint;
	// 小说路径
	private String bookPath = Constants.BOOKPATH;
	// 小说标题
	private String bookTitle = "重生完美时代";
	// 本章标题
	private String bookSecTitle;
	// 字体
	private float textSize = Constants.DEFAULT_BOOKCONTENT_TEXTSIZE;
	private float titleSize = Constants.DEFAULT_BOOKTITLE_TEXTSIZE;
	// 行距
	private float textSpacing = Constants.DEFAULT_BOOKCONTENT_SPACING;
	// 文字上下左右边距
	private float marginTop = Constants.DEFAULT_BOOKCONTENT_MARGINTOP;
	private float marginBottom = Constants.DEFAULT_BOOKCONTENT_MARGINBOTTOM;
	private float marginLeft = Constants.DEFAULT_BOOKCONTENT_MARGINLEFT;
	private float marginRight = Constants.DEFAULT_BOOKCONTENT_MARGINRIGHT;
	private float paddingTop = Constants.DEFAULT_BOOKCONTENT_PADDINGTOP;
	private float paddingBottom = Constants.DEFAULT_BOOKCONTENT_PADDINGBOTTOM;
	private float paddingLeft = Constants.DEFAULT_BOOKCONTENT_PADDINGLEFT;
	private float paddingRight = Constants.DEFAULT_BOOKCONTENT_PADDINGRIGHT;
	// 屏幕尺寸
	private float screenWidth, screenHeight;
	// 文字区域尺寸
	private float visibleWidth, visibleHeight;
	// 文字最大行数
	private int maxLineCount;
	// 往后读取时，若下一段文字是标题，则不再读取
	private boolean isBreakReturn;
	// 文本缓冲区首尾下标
	private int mbbStartIndex, mbbEndIndex;
	// 小说目录
	private static List<Category> categories;
	// 本页显示的文字
	private List<String> lines;
	// 本页显示的文字
	private StringBuilder words;
	// 分页数据，key为每一页第一个字的下标，value为页码
//	private Map<Integer, Integer> pagination;
	// 总页码
	private Integer pageTotal;
	// 当前页码
	private Integer pageNumber;
	// 页码显示的文字   当前页/总页码
	private String pageShowText, pagePercentShowText;
	// 保留两位小数
	private DecimalFormat decimalFormat = new DecimalFormat("0.00");
	// 页面背景图片
	private Bitmap backGroundBitmap;
	// 标记是否为首页、尾页
	private boolean pageFirst, pageLast;
	// 参数存储类
	private SharedPreferences preference;
	private SharedPreferences.Editor editor;
	// 数据库工具
	private DBHelper dbHelper;
	private int bookId;
	
	/**
	 * 构造函数
	 */
	public BookFactory(float sWidth, float sHeight, SharedPreferences preference){
		this.screenWidth = sWidth;
		this.screenHeight = sHeight;
		this.preference = preference;
		
		// 加载文件
		loadBook(bookPath);
		
		// 初始化工厂工具各项参数
		initFactory();
	}
	
	/**
	 * 初始化工厂工具各项参数
	 */
	public void initFactory(){
		
		visibleWidth = screenWidth - (marginLeft + marginRight + paddingLeft + paddingRight);
		visibleHeight = screenHeight - (marginTop + marginBottom + paddingTop + paddingBottom);
		
		// 获取缓存中保存的字体参数
		textSize = preference.getFloat(Constants.PREFERENCE_KEY_TEXTSIZE, textSize);
		
		// 计算文字最大行数
		maxLineCount = (int) (visibleHeight / (textSize + textSpacing));
		
		// 获取缓存中保存的上次阅读位置
		mbbStartIndex = preference.getInt(Constants.PREFERENCE_KEY_MBBINDEX, 0);
		mbbEndIndex = preference.getInt(Constants.PREFERENCE_KEY_MBBINDEX, 0);
		
		// 初始化正文画笔
		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setTextSize(textSize);
		// 初始化标题画笔
		mTitlePaint = new Paint();
		mTitlePaint.setAntiAlias(true);
		mTitlePaint.setTextSize(titleSize);
		mTitlePaint.setColor(Color.DKGRAY);
		mTitlePaint.setTextAlign(Align.LEFT);
		// 初始化章节目录画笔
		mSecTitlePaint = new Paint();
		mSecTitlePaint.setAntiAlias(true);
		mSecTitlePaint.setTextSize(titleSize);
		mSecTitlePaint.setColor(Color.DKGRAY);
		mSecTitlePaint.setTextAlign(Align.RIGHT);
		// 初始化分页百分比画笔
		mPagePercentPaint = new Paint();
		mPagePercentPaint.setAntiAlias(true);
		mPagePercentPaint.setColor(Color.DKGRAY);
		mPagePercentPaint.setTextSize(titleSize);
		mPagePercentPaint.setTextAlign(Align.LEFT);
		// 初始化分页百分比画笔
		mPagePercentPaint2 = new Paint();
		mPagePercentPaint2.setAntiAlias(true);
		mPagePercentPaint2.setColor(Color.DKGRAY);
		mPagePercentPaint2.setTextSize(titleSize);
		mPagePercentPaint2.setTextAlign(Align.RIGHT);
		// 初始化分页页码画笔
		mPaginationPaint = new Paint();
		mPaginationPaint.setAntiAlias(true);
		mPaginationPaint.setTextSize(titleSize);
		mPaginationPaint.setColor(Color.DKGRAY);
		mPaginationPaint.setTextAlign(Align.CENTER);
	}
	
	/**
	 * 加载文件
	 */
	public void loadBook(String path){
		try {
//			path = "/external/file/230561";
			totalLength = new File(path).length();
			mappedByteBuffer = new RandomAccessFile(path, "r")
					.getChannel()
					.map(FileChannel.MapMode.READ_ONLY, 0, totalLength);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 画文字
	 */
	public void doDraw(Canvas canvas) {
		// 设置页面背景图片
		canvas.drawBitmap(backGroundBitmap, 0, 0, null);
		
		// 循环打印本页文字
		words = new StringBuilder();
		for (int i = 0; i < lines.size(); i++) {
			String line = lines.get(i);
			words.append(line);
			canvas.drawText(line, marginLeft + paddingLeft, marginTop + paddingTop + (textSize + textSpacing) * (i + 1), mTextPaint);
		}
		
		// 画标题
		canvas.drawText(bookTitle, marginLeft + paddingLeft, marginTop + titleSize, mTitlePaint);
		// 画本章节目录
		canvas.drawText(bookSecTitle, screenWidth - marginRight - paddingRight, marginTop + titleSize, mSecTitlePaint);
//		// 画分页页码
//		canvas.drawText(pageShowText, screenWidth / 2, screenHeight - marginBottom, mPaginationPaint);
		// 画分页百分比
		canvas.drawText(pagePercentShowText, screenWidth - marginRight - paddingRight, screenHeight - marginBottom, mPagePercentPaint2);
		
		// 保存当前阅读位置
		editor = preference.edit();
		editor.putInt(Constants.PREFERENCE_KEY_MBBINDEX, mbbStartIndex);
		editor.commit();
	}
	
//	// 画智能断章进度
//	public void drawPercent(String text, Canvas canvas){
//		doDraw(canvas);
//		canvas.drawText(text, marginLeft, screenHeight - marginBottom, mPagePercentPaint);
//	}
	
	/**
	 * 获取页面当前位置的标题
	 */
	public void getBookSecTitle(){
		bookSecTitle = dbHelper.findCategoryByPosition(mbbStartIndex);
	}
	
	/**
	 * 获取当前页面页码和百分比
	 */
	public void getPageNumberShowText(){
		
		pageShowText = " ";
		pageTotal = preference.getInt(Constants.PREFERENCE_KEY_PAGETOTAL, 0);
		
		// 如果分页还未完成，不显示
		if(pageTotal > 0){
			pageNumber = preference.getInt(Constants.PREFERENCE_KEY_PAGENUMBERKEY + mbbStartIndex, 0);
			pageShowText = pageNumber + "/" + pageTotal;
		}
		
		// 保留两位小数
		pagePercentShowText = decimalFormat.format(mbbStartIndex * 1.0 / totalLength * 100) + "%";
	}
	
	/**
	 * 获取下一页显示文字
	 */
	public void pageNext(){
		// 向后翻页时，新页的开始为当前页的结束
		mbbStartIndex = mbbEndIndex;
	
		// 读取下一页的文字
		lines = readTextNext(new ArrayList<String>());
		
		// 获取当前位置的标题
		getBookSecTitle();
		
		// 获取当前页面页码
		getPageNumberShowText();
	}
	
	/**
	 * 获取上一页显示文字
	 */
	public void pagePre(){
		// 向前翻页时，新页的结束为当前页的开始
		mbbEndIndex = mbbStartIndex;
		
		// 读取上一页的文字
		lines = readTextPre(new ArrayList<String>());
		
		// 获取当前位置的标题
		getBookSecTitle();
		
		// 获取当前页面页码
		getPageNumberShowText();
	}
			
	/**
	 * 读取下一页的文字
	 */
	private List<String> readTextNext(List<String> lines_){
		// 若下一段文字是标题，则不再读取
		isBreakReturn = false;
		
		try {
			// 若本页文字行数小于最大行数，则继续读取下一段
			while(lines_.size() < maxLineCount && mbbEndIndex < totalLength){
				// 读取一段并转换为string
				byte[] paraBytes = readOneParaNext(mbbEndIndex);
				// 刷新下次读取时的下标
				mbbEndIndex += paraBytes.length;
				String oneLine = new String(paraBytes, Constants.DEFAULT_CHARSET);
				
				// 若下一段文字是标题，则不再读取，标题要分页
				String title = validTitleText(oneLine);
				if(lines_.size() > 0 && !"".equals(title)){
					mbbEndIndex -= paraBytes.length;
					isBreakReturn = true;
					break;
				}
				
				// 实现首行缩进 TODO
//				oneLine = Constants.FIRST_LINE_INDENT + oneLine.replaceFirst(Constants.REGEX_PATTERN_PARAGRAGH, "");
				
				while(oneLine.length() > 0){
					// 测量一行显示的文字数，返回下标
					int lineIndex = mTextPaint.breakText(oneLine, true, visibleWidth, null);
					
					// 以行为单位保存本页显示的文字
					lines_.add(oneLine.substring(0, lineIndex));
					
					// 该段文字截取后的剩余
					oneLine = oneLine.substring(lineIndex);
					
					// 超出最大行数则停止
					if(lines_.size() >= maxLineCount){
						break;
					}
				}
				
				// 若截取后还有剩余，则刷新截取下标
				if(oneLine.length() != 0){
					mbbEndIndex -= oneLine.getBytes(Constants.DEFAULT_CHARSET).length;
				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return lines_;
	}

	/**
	 * 读取上一页的文字
	 */
	private List<String> readTextPre(List<String> lines_){
		try {
			// 若读到上一标题，则转向向后读取文字
			boolean isStopPre = false;
			// 若本页文字行数小于最大行数，则继续读取下一段
			while(lines_.size() < maxLineCount){
				// 读取一段并转换为string
				byte[] paraBytes = readOneParaPre(mbbStartIndex);
				// 刷新下次读取时的下标
				mbbStartIndex -= paraBytes.length;
				String oneLine = new String(paraBytes, Constants.DEFAULT_CHARSET);
				
				// 若上一段文字为标题，则不再继续往上读
				if(!"".equals(validTitleText(oneLine))){
					isStopPre = true;
				}
				
				List<String> linesTemp = new ArrayList<String>();
				while(oneLine.length() > 0){
					// 测量一行显示的文字数，返回下标
					int lineIndex = mTextPaint.breakText(oneLine, true, visibleWidth, null);
					
					// 以行为单位保存本页显示的文字
					linesTemp.add(oneLine.substring(0, lineIndex));
					
					// 该段文字截取后的剩余
					oneLine = oneLine.substring(lineIndex);
				}
				
				// 逆序读取时，每读一段都放在list的最前面
				lines_.addAll(0, linesTemp);
				
				// 若已经读到小说最开始或者读到上一标题，且文字总长度未满，则转向向后读取文字，若后一段文字为标题，则不再读
				if((mbbStartIndex == 0 || isStopPre) && lines_.size() < maxLineCount){
//					lines_.addAll(readTextNext(lines_));
					readTextNext(lines_);
					if(isBreakReturn){
						break;
					}
				}
			}
			
			// 从第一行开始截取超出长度的文字isFirstLineStart
			while(lines_.size() > maxLineCount){
				mbbStartIndex += lines_.get(0).getBytes(Constants.DEFAULT_CHARSET).length;
				lines_.remove(0);
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return lines_;
	}
	
	/**
	 * 正序读取一段文字 
	 */
	private byte[] readOneParaNext(int tempIndex) {

		byte oneByte = 0;
		int i = tempIndex;
		// 读到换行符（0x0a）为止
		while (oneByte != 0x0a) {
			oneByte = mappedByteBuffer.get(i);
			i++;
		}
		
		// 根据下标重新读取本段文字（i绝对会大于 mbbStartIndex）
		int byteSize = i - tempIndex;
		byte[] paraBytes = new byte[byteSize];
		for (int j = 0; j < byteSize; j++) {
			paraBytes[j] = mappedByteBuffer.get(tempIndex + j);
		}
		return paraBytes;
	}
	
	/**
	 * 逆序读取一段文字
	 */
	private byte[] readOneParaPre(int tempIndex){
		
		byte oneByte = 0;
		int i = tempIndex;
		// 读到换行符（0x0a）为止
		i = tempIndex - 1;
		while (i > 0) {
			oneByte = mappedByteBuffer.get(i);
			if(oneByte == 0x0a && i != tempIndex - 1){
				i++;
				break;
			}
			i--;
		}
		
		// i最小为0
		i = i < 0 ? 0 : i;
		
		// 根据下标重新读取本段文字（i绝对会小于 mbbStartIndex）
		int byteSize = tempIndex - i;
		byte[] paraBytes = new byte[byteSize];
		for (int j = 0; j < byteSize; j++) {
			paraBytes[j] = mappedByteBuffer.get(i + j);
		}
		return paraBytes;
	}

	/**
	 * 获取小说的目录（智能断章）
	 */
	public void startAnalyzeCategories(){
		try {
			
			// 从数据库读取目录
			categories = dbHelper.getCategories(bookId);
			
			// 开始全文匹配章节目录
			List<Category> templist = new ArrayList<Category>();
			Category category = null;
			// 小说断章时读取文字下标
			int tempMbbIndex = 0;
			byte[] paraByte;
			String paraText;
			String cate;
			while(tempMbbIndex < totalLength){
				// 读取一段文字
				paraByte = readOneParaNext(tempMbbIndex);
				tempMbbIndex += paraByte.length;
				paraText = new String(paraByte, Constants.DEFAULT_CHARSET);
				
				// 正则匹配
				cate = validTitleText(paraText);
				if(!"".equals(cate)){
					cate = cate.replaceAll(Constants.REGEX_PATTERN_SECTITLE, "");
					category = new Category();
					category.setBookId(bookId);
					category.setName(cate);
					category.setPosition(tempMbbIndex - paraByte.length);
					templist.add(category);
				}
			}
			
			// 重新断章完成后，再将章节目录保存入库
			categories.clear();
			categories.addAll(templist);
			dbHelper.addCategories(bookId, categories);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 验证该行文字是否为标题，返回标题
	 */
	public String validTitleText(String text){
		String result = "";
		Pattern pattern = Pattern.compile(Constants.REGEX_PATTERN_CATEGORY);
		Matcher matcher = pattern.matcher(text);
		if(matcher.find()){
			result = matcher.group() == null ? "" : matcher.group();
		}
		return result;
	}
	
//	/**
//	 * 开始计算分页
//	 */
//	private int tempMbbIndex;
//	@SuppressLint("UseSparseArrays") 
//	public void startPagination(){
//		// 若缓存文件中的总页码参数存在，则不再重新分页
//		pageTotal = preference.getInt(Constants.PREFERENCE_KEY_PAGETOTAL, 0);
//		if(pageTotal > 0){
//			return;
//		}
//		
//		// 下标和页码
//		editor = preference.edit();
////		int tempMbbIndex = 0;
//		int tempPageNum = 0;
//		
//		// 开始分页读取文字
//		while(tempMbbIndex < totalLength){
//			// 存放分页，key为每一页第一个字的下标，value为页码
//			editor.putInt(Constants.PREFERENCE_KEY_PAGENUMBERKEY + tempMbbIndex, tempPageNum++);
//			
//			// ***********一下逻辑为pageNext的内容*********
//			int lineCount = 0;
//			try {
//				// 若本页文字行数小于最大行数，则继续读取下一段
//				while(lineCount < maxLineCount && tempMbbIndex < totalLength){
//					// 读取一段并转换为string
//					byte[] paraBytes = readOneParaNext(tempMbbIndex);
//					// 刷新下次读取时的下标
//					tempMbbIndex += paraBytes.length;
//					String oneLine = new String(paraBytes, Constants.DEFAULT_CHARSET);
//					
//					// 若下一段文字是标题，则不再读取，标题要分页
//					String title = validTitleText(oneLine);
//					if(lineCount > 0 && !"".equals(title)){
//						tempMbbIndex -= paraBytes.length;
//						break;
//					}
//					
//					// 实现首行缩进 TODO
////					oneLine = Constants.FIRST_LINE_INDENT + oneLine.replaceFirst(Constants.REGEX_PATTERN_PARAGRAGH, "");
//					
//					// 超出最大行数则停止
//					while(oneLine.length() > 0 && lineCount < maxLineCount){
//						// 测量一行显示的文字数，返回下标
//						int lineIndex = mTextPaint.breakText(oneLine, true, visibleWidth, null);
//						
//						// 该段文字截取后的剩余
//						oneLine = oneLine.substring(lineIndex);
//						
//						// 以行为单位保存本页显示的文字
//						lineCount++;
//					}
//					
//					// 若截取后还有剩余，则刷新截取下标
//					if(oneLine.length() != 0){
//						tempMbbIndex -= oneLine.getBytes(Constants.DEFAULT_CHARSET).length;
//					}
//				}
//			} catch (UnsupportedEncodingException e) {
//				e.printStackTrace();
//			}
//		}
//		
//		// 总页码数
//		pageTotal = tempPageNum;
//		editor.putInt(Constants.PREFERENCE_KEY_PAGETOTAL, pageTotal);
//		editor.commit();
//	}
	
	/**
	 * 获取当前已分析出来的目录
	 */
	public static List<String> getToShowCategories(){
		List<Category> temp = new ArrayList<Category>();
		temp.addAll(categories);
		List<String> result = new ArrayList<String>();
		for(Category c : temp){
			result.add(c.getName());
		}
		return result;
	}
	
	/**
	 * 获取已经断章后的目录
	 */
	public List<Category> getCategories(){
		return categories;
	}

	/**
	 * 获取分页进度 TODO
	 */
//	public float getCategoryPercent() {
//		return tempMbbIndex*1.0f/totalLength*100;
//	}
	
	/**
	 * 初始化文字背景图片
	 */
	public void setBackGroundBitmap(Bitmap backGroundBitmap) {
		this.backGroundBitmap = backGroundBitmap;
	}

	/**
	 * 标记是否首页
	 */
	public boolean isPageFirst() {
		pageFirst = mbbStartIndex <= 0;
		return pageFirst;
	}

	/**
	 * 标记是否尾页
	 */
	public boolean isPageLast() {
		pageLast = mbbEndIndex >= totalLength;
		return pageLast;
	}
	
	public void setDBHelper(DBHelper dbHelper){
		this.dbHelper = dbHelper;
	}
	
	public void setBookId(int bookId){
		this.bookId = bookId;
	}
	
	/**
	 * 字体变化
	 * changeState：0-变小，非0-变大
	 */
	public boolean changeTextSize(int changeState){
		if((this.textSize <= 12 && changeState == 0) || (this.textSize >= 40 && changeState == 1)){
			return false;
		}
		if(changeState == 0){
			this.textSize -= 2;
		}else{
			this.textSize += 2;
		}
		editor = preference.edit();
		editor.putFloat(Constants.PREFERENCE_KEY_TEXTSIZE, textSize);
		editor.commit();
		return true;
	}
	
	/**
	 * 获取本页文字
	 */
	public List<String> getLines(){
		return lines;
	}
	
}
